﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WorkFlowCore.Authorization;
using WorkFlowCore.Conditions;
using WorkFlowCore.Framework.UserSelectors;
using WorkFlowCore.Host.ViewModels;
using WorkFlowCore.Host.ViewModels.WorkFlowCore;
using WorkFlowCore.UserSelectors;
using WorkFlowCore.Workflows;
using WorkFlowCore.WorkTasks;
using Mapster;
using WorkFlowCore.IRepositories;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Application.Dtos;

namespace WorkFlowCore.Host.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class WorkFlowController : AbpControllerBase
    {
        private ConditionManager conditionManager;
        private WorkflowManager workflowManager;
        private WorkTaskManager workTaskManager;
        private IBasicRepository<Workflow,Guid> workflowRepository;
        private IWorkTaskRepository worktaskRepository;
        private IBasicRepository<WorkflowVersionInfo, Guid> versionRepository;
        private IBasicRepository<WorkStepInfo, Guid> workStepRepository;
        private IWorkflowSession workflowSession;


        public WorkFlowController(ConditionManager conditionManager, WorkflowManager workflowManager, IBasicRepository<Workflow, Guid> workflowRepository, IWorkTaskRepository worktaskRepository, IBasicRepository<WorkflowVersionInfo, Guid> versionRepository, IBasicRepository<WorkStepInfo, Guid> workStepRepository, IWorkflowSession workflowSession, WorkTaskManager workTaskManager)
        {
            this.conditionManager = conditionManager;
            this.workflowManager = workflowManager;
            this.workflowRepository = workflowRepository;
            this.worktaskRepository = worktaskRepository;
            this.versionRepository = versionRepository;
            this.workStepRepository = workStepRepository;
            this.workflowSession = workflowSession;
            this.workTaskManager = workTaskManager;
        }
        /// <summary>
        /// 获取所有条件
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllconditions")]
        public async Task<IEnumerable<ConditionDto>> GetAllconditions()
        {
            return ConditionManager.AllConditions.Select(c => new ConditionDto { Id = c.Id, Name = c.Name,Description=c.Description });
        }
        /// <summary>
        /// 获取所有的用户选择器
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllUserSelectors")]
        public async Task<IEnumerable<UserSeletorDto>> GetAllUserSelectors()
        {
            return UserSelectorManager.UserSelectors.Select(us => new UserSeletorDto { Id = us.Id, Name = us.Name, Description = us.Description });
        }
        /// <summary>
        /// 获取用户选择器所提供的选项
        /// </summary>
        /// <param name="userSelectorId"></param>
        /// <returns></returns>
        [HttpGet("GetUserSelectionsOfUserSelector")]
        public async Task<List<Selection>> GetUserSelectionsOfUserSelector(string userSelectorId)
        {
            return workTaskManager.GetUserSelectionsOfUserSelector(userSelectorId).Result;
        }

        /// <summary>
        /// 创建新流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateWorkFlow")]
        public async Task<Workflow> CreateWorkFlow(CreateWorkFlowInput input)
        {
            return await workflowManager.CreateWorkflow($"WF{DateTime.Now.ToString("yyyMMddHHmmssfff")}", input.Name, input.Des);
        }
        ///// <summary>
        ///// 获取所有流程列表
        ///// </summary>
        ///// <returns></returns>
        //[HttpGet("GetAllWorkflows")]
        //public async Task<List<Workflow>>> GetAllWorkflows()
        //{
        //    return (await workflowRepository.GetListAsync()).OrderByDescending(w=>w.CreationTime).ToList());
        //}
        /// <summary>
        /// 获取流程所有版本信息
        /// </summary>
        /// <param name="workflowId"></param>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowVersions")]
        public async Task<IEnumerable<GetAllWorkflowVersionOutput>> GetAllWorkflowVersions(Guid workflowId)
        {
            return (await  versionRepository.GetListAsync(v => v.WorkflowId == workflowId)).Select(v => new GetAllWorkflowVersionOutput
            {
                WorkflowId = v.WorkflowId,
                VersionNo = v.VersionNo,
                Description = v.Description,
                CreationTime = v.CreationTime,
                ModifiedTime = v.ModifiedTime
            });
        }
        /// <summary>
        /// 获取流程具体版本信息
        /// </summary>
        /// <param name="versionId"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("GetWorkflowVersion")]
        public async Task<GetWorkflowVersionOutput> GetWorkflowVersion(int versionId, Guid id)
        {
            var version = await workflowManager.GetWorkflowVersion(id, versionId);
            return version.Adapt<GetWorkflowVersionOutput>();
        }
        /// <summary>
        /// 删除流程
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("Delete")]
        public async Task<bool> Delete(Guid id)
        {
            var result = await workflowManager.DeleteWorkflow(id);
            return result;
        }

        /// <summary>
        /// 删除流程
        /// </summary>
        /// <param name="id"></param>
        /// <param name="versionId"></param>
        /// <returns></returns>
        [HttpDelete("DeleteWorkflowVersion")]
        public async Task<bool> DeleteWorkflowVersion(Guid id, int versionId)
        {
            var result = await workflowManager.DeleteWorkflowVersion(id, versionId);
            return result;
        }
        /// <summary>
        /// 更新流程激活的版本
        /// </summary>
        /// <param name="input"></param>
        [HttpPut("UpdateWorkflowActiveVersion")]
        public async Task<bool> UpdateWorkflowActiveVersion(UpdateWorkflowActiveVersionInput input)
        {
            var result =await workflowManager.UpdateWorkflowActiveVersion(input.WorkflowId, input.ActiveVersion);
            return result;
        }


        /// <summary>
        /// 更新流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>f
        [HttpPut("UpdateWorkFlow")]
        public async Task<Workflow> UpdateWorkFlow(UpdateWorkFlowInput input)
        {
            return await workflowManager.UpdateWorkflow(input.WorkflowId.Id, input.Name, input.Des, input.WorkflowId.VersionId, input.DrawingInfo, input.VersionDescription
                , input.WorkflowLines.Select(line => new WorkflowLine(line.Name, input.WorkflowId, line.FromNodeId, line.ToNodeId, line.Conditions)).ToList()
                , input.WorkflowNodes.Select(node => new WorkflowNode(node.Id, input.WorkflowId, node.Name, node.NodeType, node.DrawingInfo, node.IsWaitingAllUser, node.UserSelectors, node.RejectNodes)).ToList());
        }

        /// <summary>
        /// 获取所有流程列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflows")]
        public async Task<PageResult<Workflow>> GetAllWorkflows([FromQuery] GetAllWorkflowInput input)
        {
            var items = await workflowRepository.GetPagedListAsync(w => !w.Deleted, input.SkipCount, input.MaxResultCount, "CreationTime desc");
            var count = await workflowRepository.GetCountAsync();
            var result = new PageResult<Workflow> { Items = items, Total = count };
            return result;
        }

        /// <summary>
        /// 创建流程任务
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateWorkTask")]
        public async Task<WorkTask> CreateWorkTask(CreateWorkTaskInput input)
        {
            input.CreatedUserId = workflowSession.User.Id;
            var worktask =  await workTaskManager.CreateWorkTask(input.WorkflowId, input.Name, input.FormData, input.EntityFullName, input.EntityKeyValue,input.CreatedUserId);
            return worktask;
        }

        /// <summary>
        /// 创建流程任务
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateSimulationWorkTask")]
        public async Task<WorkTask> CreateSimulationWorkTask(CreateWorkTaskInput input)
        {
            var worktask = await workTaskManager.CreateSimulationWorkTask(input.WorkflowId, input.Name, input.FormData, input.EntityFullName, input.EntityKeyValue, input.CreatedUserId);
            return worktask;
        }

        /// <summary>
        /// 获取流程任务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("GetWorkTask")]
        public async Task<WorkTask> GetWorkTask(Guid id)
        {
            var worktask = await workTaskManager.GetWorkTaskAsync(id);
            return worktask;
        }


        /// <summary>
        /// 发起流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("StartWorkTask")]
        public  async Task<List<WorkStep>>  StartWorkTask(StartWorkTaskInput input)
        {
            var steps = await workTaskManager.WorkTaskStart(input.WorktaskId);
            return steps;
        }
        /// <summary>
        /// 通过审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("PassProve")]
        public async Task<List<WorkStep>> PassProve(ProveInput input)
        {
            var proveResult = await workTaskManager.PassApprove(input.StepId, input.Comment, input.ResourceIds,input.FormData);
            if (proveResult.Code == ProveResult.ProveResultCode.FAIL)
                new Exception(proveResult.Msg);
            return proveResult.WorkSteps;
        }
        /// <summary>
        /// 驳回审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("RejectProve")]
        public async Task<List<WorkStep>> RejectProve(RejectProveInput input)
        {
            var proveResult = await workTaskManager.RejectApprove(input.StepId, input.Comment, input.ResourceIds, input.FormData, input.RejectToNodeId);
            if (proveResult.Code == ProveResult.ProveResultCode.FAIL)
                new Exception(proveResult.Msg);
            return proveResult.WorkSteps;
        }
        /// <summary>
        /// 撤回审批
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("WithdrawProve")]
        public async Task<List<WorkStep>> WithdrawProve(ProveInput input)
        {
            var proveResult = await workTaskManager.Withdraw(input.StepId, input.Comment);
            if (proveResult.Code == ProveResult.ProveResultCode.FAIL)
                new Exception(proveResult.Msg);
            return proveResult.WorkSteps;
        }
        /// <summary>
        /// 转发代办
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("ForwardProve")]
        public async Task<List<WorkStep>> ForwardProve(ForwardProveInput input)
        {
            var proveResult = await workTaskManager.Forward(input.StepId, input.UserSelectors, input.Comment);
            if (proveResult.Code == ProveResult.ProveResultCode.FAIL)
                new Exception(proveResult.Msg);
            return proveResult.WorkSteps;
        }
        /// <summary>
        /// 获取所有审批步骤
        /// </summary>
        /// <param name="worktaskId"></param>
        /// <returns></returns>
        [HttpGet("GetAllTaskStepsOfWorkTask")]
        public async Task<List<WorkStep>> GetAllTaskStepsOfWorkTask(Guid worktaskId)
        {
            //获取所有过程输出
            var historySteps =await workTaskManager.GetAllTaskStepsOfWorkTaskAsync(worktaskId);
            return historySteps;
        }
        /// <summary>
        /// 清除模拟 记录
        /// </summary>
        /// <returns></returns>
        [HttpPost("ClearSimulationRecord")]
        public async Task<object> ClearSimulationRecord()
        {            
            await workTaskManager.ClearSimulationRecord();

            return OutputDto.Succeed<object>(null);
        }

        /// <summary>
        /// 获取所有用户（仅模拟用户）
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllUserForSimulation")]
        public async Task<List<User>>GetAllUserForSimulation()
        {
            return UserList.Users.Select(u=>new UserSelectors.User { Id=u.Id,Name=u.Name}).ToList();
        }

        /// <summary>
        /// 获取所有审批步骤
        /// </summary>
        /// <param name="worktaskId"></param>
        /// <returns></returns>
        [HttpGet("GetAllTaskStepsOfWorkTaskByEntityInfo")]
        public async Task<List<WorkStep>> GetAllTaskStepsOfWorkTaskByEntityInfo(string entityFullName, string entityKeyValue)
        {
            //获取所有过程输出
            var historySteps = await workTaskManager.GetAllTaskStepsOfWorkTaskByEntityInfoAsync(entityFullName, entityKeyValue);
            return historySteps;
        }



        private async Task FillWorktaskInfo(List<WorkTaskDto> workTasks)
        {
            var workflows = await workflowRepository.GetListAsync(w => workTasks.Select(s => s.WorkflowId.Id).Contains(w.Id));
            workTasks.ForEach(i =>
            {
                i.WorkflowId.WorkflowName = workflows.FirstOrDefault(w => w.Id == i.WorkflowId.Id && w.ActiveVersion == i.WorkflowId.VersionId)?.Name;
            });
        }

        /// <summary>
        /// 获取用户待处理的流程
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetUnHandledWorkTasksOfUser")]
        public async Task<PageResult<WorkTaskDto>> GetUnHandledWorkTasksOfUser([FromQuery] GetUnHandledWorkTasksOfUserInput input)
        {
            var worktasks = await workTaskManager.GetUnHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount);
            var result = new PageResult<WorkTaskDto>
            {
                Items = worktasks.Items.Adapt<List<WorkTaskDto>>(),// mapper.Map<List<WorkTask>, List<WorkTaskDto>>(worktasks.Items),
                Total = worktasks.Total
            };
            await FillWorktaskInfo(result.Items);

            return result;

        }

        /// <summary>
        /// 获取用户已处理的流程
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetHandledWorkTasksOfUser")]
        public async Task<PageResult<WorkTaskDto>> GetHandledWorkTasksOfUser([FromQuery] GetHandledWorkTasksOfUserInput input)
        {
            var worktasks = await workTaskManager.GetHandledWorkTasksOfUserAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount);
            var result = new PageResult<WorkTaskDto>
            {
                Items = worktasks.Items.Adapt<List<WorkTaskDto>>(),// mapper.Map<List<WorkTask>, List<WorkTaskDto>>(worktasks.Items),
                Total = worktasks.Total
            };

            await FillWorktaskInfo(result.Items);

            return result;
        }
        /// <summary>
        /// 根据实体类型获取所有的处理中的工作流
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [HttpGet("GetAllProcessingWorkTasksByEntityType")]
        public async Task<List<WorkTask>> GetAllProcessingWorkTasksByEntityType([FromQuery] GetAllProcessingWorkTasksByEntityTypeInput input)
        {
            var worktaskInfos = await worktaskRepository.GetListAsync(wt => input.EntityKeyValues.Contains(wt.EntityKeyValue) && !wt.Deleted && wt.EntityFullName == input.EntityFullName);
            return worktaskInfos.Select(wt => wt.ToWorkTask()).ToList();
        }
        [HttpGet("GetWorkTasksOfCreator")]
        public async Task<PageResult<WorkTaskDto>> GetWorkTasksOfCreator([FromQuery] GetWorkTasksOfCreatorInput input)
        {
            var worktasks = await worktaskRepository.GetWorkTasksOfCreatorAsync(workflowSession.User.Id, input.CurrentPage, input.MaxResultCount);
            var result = new PageResult<WorkTaskDto>
            {
                Items = worktasks.Items.Adapt<List<WorkTaskDto>>(), //mapper.Map<List<WorkTask>, List<WorkTaskDto>>(worktasks.Items),
                Total = worktasks.Total
            };

            await FillWorktaskInfo(result.Items);

            return result;
        }

        [HttpGet("GetAllWorkTasks")]
        public async Task<PageResult<WorkTaskDto>> GetAllWorkTasks([FromQuery] GetAllWorkTasksInput input)
        {
            var worktasks = await worktaskRepository.GetAllWorkTasksAsync(input.CurrentPage, input.MaxResultCount);
            var result = new PageResult<WorkTaskDto>
            {
                Items = worktasks.Items.Adapt<List<WorkTaskDto>>(), //mapper.Map<List<WorkTask>, List<WorkTaskDto>>(worktasks.Items),
                Total = worktasks.Total
            };

            await FillWorktaskInfo(result.Items);

            return result;
        }
        [HttpGet("GetRejectNodes")]
        public async Task<List<WorkflowNodeDto>> GetRejectNodes([FromQuery] GetRejectNodesInput input)
        {
            var data = await workTaskManager.GetRejectNodes(input.WorkStepId);
            var result = data.Adapt<List<WorkflowNodeDto>>();
            return result;
        }

        [HttpPut("CancelWorkTask")]
        public async Task<WorkTaskDto> CancelWorkTask(EntityDto<Guid> input)
        {
            var workTaskInfo = await worktaskRepository.GetAsync(input.Id);
            var workTask = workTaskInfo.ToWorkTask();
            workTask.Cancel();
            await worktaskRepository.UpdateAsync(workTask.ToWorkTaskInfo(workTaskInfo));
            var result = workTask.Adapt<WorkTaskDto>();
            return result;
        }

        [HttpPost("CopyWorkTask")]
        public async Task<WorkTaskDto> CopyWorkTask(EntityDto<Guid> input)
        {
            var workTaskInfo = await worktaskRepository.GetAsync(input.Id);
            var workTask = workTaskInfo.ToWorkTask();
            var newWorkTask = workTask.Copy();
            await worktaskRepository.InsertAsync(newWorkTask.ToWorkTaskInfo());
            var result = newWorkTask.Adapt<WorkTaskDto>();
            return result;
        }

        /// <summary>
        /// 获取所有流程列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowsWithVersion")]
        public async Task<List<GetAllWorkflowsWithVersionOutput>> GetAllWorkflowsWithVersion()
        {
            var workflows =  await workflowManager.GetAllWorkflowsWithVersion();
            return workflows.Adapt<List<GetAllWorkflowsWithVersionOutput>>();
        }
        /// <summary>
        /// 删除审批任务
        /// </summary>
        /// <returns></returns>
        [HttpDelete("DeleteWorkTask")]
        public async Task DeleteWorkTaskAsync(Guid id)
        {
            await workTaskManager.DeleteWorkTask(id);
        }

        /// <summary>
        /// 更新流程表单
        /// </summary>
        /// <returns></returns>
        [HttpPut("UpdateWorkTaskFormData")]
        public async Task UpdateWorkTaskFormData(UpdateWorkTaskFormDataInput input)
        {
            var workTaskInfo = await worktaskRepository.GetAsync(input.Id);
            if (workTaskInfo == null) return;
            var workTask = workTaskInfo.ToWorkTask();
            workTask.UpdateFormData(input.FormData);
            await worktaskRepository.UpdateAsync(workTask.ToWorkTaskInfo(workTaskInfo));
        }
    }
}
